package cn.edu.fzu.delivery.service.impl;

import cn.edu.fzu.delivery.cache.AreaCache;
import cn.edu.fzu.delivery.domain.entity.NetWorkDay;
import cn.edu.fzu.delivery.domain.entity.Network;
import cn.edu.fzu.delivery.domain.entity.NetworkApply;
import cn.edu.fzu.delivery.domain.entity.SysUser;
import cn.edu.fzu.delivery.domain.enums.NetWorkStatusEnum;
import cn.edu.fzu.delivery.domain.enums.NetworkApplyStatusEnum;
import cn.edu.fzu.delivery.domain.enums.UserTypeEnum;
import cn.edu.fzu.delivery.exception.ServiceException;
import cn.edu.fzu.delivery.mapper.NetWorkDayMapper;
import cn.edu.fzu.delivery.mapper.NetworkApplyMapper;
import cn.edu.fzu.delivery.mapper.NetWorkMapper;
import cn.edu.fzu.delivery.service.NetworkService;
import cn.edu.fzu.delivery.service.UserService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

/**
 * @author yifan
 * @date 2022/11/6
 */
@Service
public class NetworkServiceImpl implements NetworkService {

    @Resource
    private NetWorkMapper      netWorkMapper;

    @Resource
    private NetworkApplyMapper networkApplyMapper;

    @Resource
    private AreaCache          areaCache;

    @Resource
    private UserService        userService;

    @Resource
    private NetWorkDayMapper   netWorkDayMapper;

    @Override
    public List<Network> listNetwork(String name, Long provinceId, Long cityId, Long areaId, String address,
                                     NetWorkStatusEnum status) {

        List<Long> areaIdList = null;
        if (areaId != null) {
            areaIdList = Collections.singletonList(areaId);
        } else if (cityId != null) {
            areaIdList = areaCache.getAreaIdsByCityId(cityId);
        } else if (provinceId != null) {
            areaIdList = areaCache.getAreaIdsByProvinceId(provinceId);
        }

        if (areaIdList != null && areaIdList.isEmpty()) {
            return Collections.emptyList();
        }

        return netWorkMapper.list(name, areaIdList, address, status);
    }


    @Override
    public List<Network> searchByName(String name) {
        return netWorkMapper.list(name, null, null, null);
    }


    @Override
    public void update(Long id, String name, Long areaId, String address, String desc, SysUser currentUser) {
        // 快递员不能修改网点，网点管理员只能修改自己的网点
        if ((currentUser.getType() == UserTypeEnum.EXPRESS) || (currentUser.getType() == UserTypeEnum.NET_ADMIN
                && !Objects.equals(currentUser.getNetwork().getId(), id))) {
            throw new ServiceException("没有访问权限");
        }
        Integer update = netWorkMapper.update(id, name, areaId, desc, address);
        if (update == 0) {
            throw new ServiceException("网点不存在");
        }
    }


    @Override
    public void updateStatus(Long id, NetWorkStatusEnum status, SysUser currentUser) {

        if (status == NetWorkStatusEnum.DELETE) {
            // 超级管理员才能删除网点
            if (currentUser.getType() != UserTypeEnum.SUPER_ADMIN) {
                throw new ServiceException("没有访问权限");
            }
            // 没有人属于该网点才能删除
            List<SysUser> sysUsers = userService.listSysUser(id, null, null, null, null, null, null);
            if (!sysUsers.isEmpty()) {
                throw new ServiceException("操作失败：存在系统人员属于该网点");
            }
        }

        // 快递员不能修改网点，网点管理员只能修改自己的网点
        if ((currentUser.getType() == UserTypeEnum.EXPRESS) || (currentUser.getType() == UserTypeEnum.NET_ADMIN
                && !Objects.equals(currentUser.getNetwork().getId(), id))) {
            throw new ServiceException("没有访问权限");
        }

        Integer updateStatus = netWorkMapper.updateStatus(id, status);
        if (updateStatus == 0) {
            throw new ServiceException("网点不存在");
        }
    }


    @Override
    public void add(String name, Long areaId, String address, String desc, SysUser currentUser) {
        if (currentUser.getType() != UserTypeEnum.SUPER_ADMIN) {
            throw new ServiceException("没有访问权限");
        }
        // 初始状态为不营业
        Integer add = netWorkMapper.add(name, areaId, address, desc, NetWorkStatusEnum.BAN);
        if (add == 0) {
            throw new ServiceException("参数错误");
        }
    }


    @Override
    public void apply(String name, Long areaId, String address, String desc, Long applicantId, SysUser curUser) {
        if (curUser.getType() != UserTypeEnum.NET_ADMIN) {
            throw new ServiceException("只有网点管理员能申请网点");
        }
        if (curUser.getNetwork() != null) {
            throw new ServiceException("您已拥有网点，不能再次申请网点");
        }
        Integer apply = networkApplyMapper.apply(name, areaId, address, desc, applicantId);
        if (apply == 0) {
            throw new ServiceException("请求参数错误");
        }
    }


    @Override
    public void handleApply(Long id, NetworkApplyStatusEnum status, SysUser currentUser) {
        if (currentUser.getType() != UserTypeEnum.NET_ADMIN) {
            throw new ServiceException("只有超级管理员能审核网点申请");
        }
        Integer result = networkApplyMapper.handleApply(id, status, currentUser.getId());
        if (result == 0) {
            throw new ServiceException("该申请不存在");
        }
        if (status == NetworkApplyStatusEnum.PASSED) {
            // todo 审核通过则根据申请信息新增网点
        }
    }


    @Override
    public List<NetworkApply> listApply(String name, Long provinceId, Long cityId, Long areaId, String address,
                                        String desc, Long applicantId, Long reviewerId, NetworkApplyStatusEnum status,
                                        Date startTime, Date endTime, SysUser currentUser) {
        if (currentUser.getType() != UserTypeEnum.SUPER_ADMIN) {
            throw new ServiceException("只有超级管理员能查看网点申请");
        }

        List<Long> areaIdList = null;
        if (areaId != null) {
            areaIdList = Collections.singletonList(areaId);
        } else if (cityId != null) {
            areaIdList = areaCache.getAreaIdsByCityId(cityId);
        } else if (provinceId != null) {
            areaIdList = areaCache.getAreaIdsByProvinceId(provinceId);
        }

        if (areaIdList != null && areaIdList.isEmpty()) {
            return Collections.emptyList();
        }
        return networkApplyMapper.list(name, areaIdList, address, desc, applicantId, reviewerId, status, startTime,
                endTime);
    }


    @Override
    public List<NetWorkDay> listNetWorkDay() {
        List<NetWorkDay> list = netWorkDayMapper.list();
        list.removeIf(netWorkDay -> netWorkDay.getNetWork1().getStatus() != NetWorkStatusEnum.NORMAL
                || netWorkDay.getNetWork2().getStatus() != NetWorkStatusEnum.NORMAL);
        return list;
    }


    @Override
    public List<NetWorkDay> listNetWorkDay(Long networkId1, Long networkId2, Integer day) {
        List<NetWorkDay> netWorkDays;
        if (networkId1 != null && networkId2 != null) {
            netWorkDays = netWorkDayMapper.listByIdsAndDay(networkId1, networkId2, day);
        } else {
            netWorkDays = netWorkDayMapper.listByIdAndDay((networkId1 != null) ? networkId1 : networkId2, day);
        }
        return netWorkDays;
    }


    @Override
    public void addNetworkDay(Long networkId1, Long networkId2, Integer day) {
        if (Objects.equals(networkId1, networkId2)) {
            throw new ServiceException("两个网点不能相同");
        }
        if (day < 0) {
            throw new ServiceException("所需天数不能为负");
        }
        List<NetWorkDay> netWorkDays = netWorkDayMapper.listByIdsAndDay(networkId1, networkId2, day);
        if (!netWorkDays.isEmpty()) {
            throw new ServiceException("俩个网点之间已存在路线");
        }
        Integer add = netWorkDayMapper.add(networkId1, networkId2, day);
        if (add == 0) {
            throw new ServiceException("添加失败");
        }
    }


    @Override
    public void deleteNetworkDay(Long id, SysUser currentUser) {
        if (currentUser.getType() != UserTypeEnum.SUPER_ADMIN) {
            throw new ServiceException("需要权限：超级管理员");
        }
        Integer delete = netWorkDayMapper.delete(id);
        if (delete == 0) {
            throw new ServiceException("删除失败");
        }
    }


    @Override
    public void updateNetworkDay(Long id, Long networkId1, Long networkId2, Integer day) {

        List<NetWorkDay> netWorkDays = netWorkDayMapper.listByIdsAndDay(networkId1, networkId2, null);
        if (!netWorkDays.isEmpty() && !Objects.equals(netWorkDays.get(0).getId(), id)) {
            throw new ServiceException("两个网点已存在路线");
        }
        if (Objects.equals(networkId1, networkId2)) {
            throw new ServiceException("两个网点不能相同");
        }
        if (day < 0) {
            throw new ServiceException("所需天数不能为负");
        }
        Integer update = netWorkDayMapper.update(id, networkId1, networkId2, day);
        if (update == 0) {
            throw new ServiceException("修改失败");
        }
    }


    @Override
    public Network getById(Long id) {
        return netWorkMapper.getById(id);
    }
}
